package tt.dz.util;

import jxl.Workbook;
import jxl.format.Alignment;
import jxl.format.Border;
import jxl.format.BorderLineStyle;
import jxl.format.VerticalAlignment;
import jxl.write.*;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import tt.dz.mvc.model.AddUserModel;
import tt.dz.util.annotation.Display;
import tt.dz.util.annotation.IgnoreInOutput;
import tt.dz.util.annotation.RelateCodeEnum;

import javax.servlet.http.HttpServletResponse;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class ExcelExporter
{
	private Log log = LogFactory.getLog(this.getClass());

	private static WritableCellFormat header_format;

	private static WritableCellFormat content_format;

	public ExcelExporter() throws WriteException
	{
		/** ************设置单元格字体************** */
		WritableFont NormalFont = new WritableFont(WritableFont.ARIAL, 10);
		WritableFont BoldFont = new WritableFont(WritableFont.ARIAL, 10, WritableFont.BOLD);

		/** ************以下设置三种单元格样式，灵活备用************ */
		// 用于标题居中
		if (header_format == null)
		{
			header_format = new WritableCellFormat(BoldFont);
			header_format.setBorder(Border.ALL, BorderLineStyle.THIN); // 线条

			header_format.setVerticalAlignment(VerticalAlignment.CENTRE); // 文字垂直对齐
			header_format.setAlignment(Alignment.CENTRE); // 文字水平对齐
			header_format.setWrap(false); // 文字是否换行
		}

		// 用于正文居左
		if (content_format == null)
		{
			content_format = new WritableCellFormat(NormalFont);
			content_format.setBorder(Border.ALL, BorderLineStyle.THIN); // 线条
			content_format.setVerticalAlignment(VerticalAlignment.CENTRE); // 文字垂直对齐
			content_format.setAlignment(Alignment.LEFT); // 文字水平对齐
			content_format.setWrap(false); // 文字是否换行
		}
	}

	public <T> void export(List<T> content, HttpServletResponse response, String fileName) throws IOException, WriteException, IllegalAccessException, IntrospectionException, InvocationTargetException
	{
		OutputStream os = response.getOutputStream();// 取得输出流
		//		response.reset();// 清空输出流
		response.setHeader("Content-disposition", "attachment; filename=" + new String(fileName.getBytes("GB2312"), "ISO8859-1"));
		response.setContentType("application/msexcel");// 定义输出类型
		export(content, os);
	}

	public <T> void export(List<T> content, OutputStream os) throws WriteException, IOException, IllegalAccessException, IntrospectionException, InvocationTargetException
	{
		WritableWorkbook workbook = null;
		if (content == null || content.isEmpty())
			return;
		try
		{

			Class clazz = content.get(0).getClass();
			Field[] fields = clazz.getDeclaredFields();

			workbook = Workbook.createWorkbook(os);
			WritableSheet sheet = workbook.createSheet("Sheet1", 0);

			/** **********设置纵横打印（默认为纵打）、打印纸***************** */
			//			jxl.SheetSettings sheetset = sheet.getSettings();
			//			sheetset.setProtected(false);

			for (int i = 0, column = 0; i < fields.length; i++)
			{
				Field field = fields[i];
				if (field.isAnnotationPresent(IgnoreInOutput.class))
					continue;
				String header;
				if (field.isAnnotationPresent(Display.class))
				{
					Display d = field.getAnnotation(Display.class);
					header = d.value();
				}
				else
					header = field.getName();
				sheet.addCell(new Label(column++, 0, header, header_format));

			}

			int row = 0;
			for (T line_obj : content)
			{
				row++;
				for (int i = 0, column = 0; i < fields.length; i++)
				{
					Field field = fields[i];
					if (field.isAnnotationPresent(IgnoreInOutput.class))
						continue;
					String value = "";
					try
					{
						Object val = PropertyUtils.getSimpleProperty(line_obj, field.getName());
						if (val != null)
						{
							value = val.toString();

							if (field.isAnnotationPresent(RelateCodeEnum.class))
							{
								RelateCodeEnum codeEnum = field.getAnnotation(RelateCodeEnum.class);
								for (EnumCodeValue codeValue : codeEnum.value().getEnumConstants())
								{
									if (codeValue.value().equals(value))
									{
										value = codeValue.desc();
										break;
									}
								}
							}
						}
					}
					catch (Exception e)
					{
						log.error("Error occurred while using the getter to get field value", e);
					}
					sheet.addCell(new Label(column++, row, value, content_format));
				}
			}
			workbook.write();
		}
		catch (IOException e)
		{
			log.error(e.getMessage(), e);
			throw e;
		}
		finally
		{
			if (workbook != null)
				workbook.close();
		}

	}
}
